package com.android.accessibility.utils;

import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.os.Build;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.android.accessibility.NetworkManager;
import com.android.accessibility.PhoneManager;
import com.android.accessibility.R;
import com.android.accessibility.service.WXObserverService;
import com.android.accessibility.stat.Stat;
import com.android.volley.RequestQueue;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;

public class AuthHelper {

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
    private static final String A = "!@#$%^&*()_)(*&^%$#@!";
    private static final String G = "%&*^&*&%&$(^*%*(^*&*%";
    private static final String AU = "authed";

    public static void showAuthDialog(final Context context, OnDismissListener l) {
        final Dialog dialog = new Dialog(context);
        dialog.setTitle("验证");
        View view = LayoutInflater.from(context).inflate(R.layout.auth_layout,
                null);
        TextView tv = (TextView) view.findViewById(R.id.auth_code);
        final EditText editText = (EditText) view
                .findViewById(R.id.auth_code_result);
        tv.setText("机器码: " + PhoneManager.get(context).getAndroidIDHashCode());
        dialog.setContentView(view);
        Button copyButton = (Button) view.findViewById(R.id.copy_auth_code);
        copyButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                ClipboardManager cmb = (ClipboardManager) context
                        .getSystemService(Context.CLIPBOARD_SERVICE);
                cmb.setText(PhoneManager.get(context).getAndroidIDHashCode());
                Toast.makeText(context, "已复制", Toast.LENGTH_SHORT).show();
            }
        });
        Button pasteButton = (Button) view.findViewById(R.id.paste_auth_code);
        pasteButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                ClipboardManager cmb = (ClipboardManager) context
                        .getSystemService(Context.CLIPBOARD_SERVICE);
                editText.setText(cmb.getText());
            }
        });
        Button authButton = (Button) view.findViewById(R.id.auth_confirm);
        authButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    String encryptedString = encrypt(PhoneManager.get(context)
                            .getAndroidIDHashCode());
                    if (!TextUtils.isEmpty(encryptedString)
                            && encryptedString.equals(editText.getText()
                                    .toString())) {
                        PreferenceManager.getDefaultSharedPreferences(context)
                        .edit().putString(AU, G).commit();
                        Toast.makeText(context, "验证成功", Toast.LENGTH_SHORT)
                        .show();
                        dialog.dismiss();
                        Map<String, Object> params = new HashMap<String, Object>();
                        String hashCode = PhoneManager.get(context).getAndroidIDHashCode();
                        String out = hashCode + " -- " + sdf.format(new Date()) + " -- " + Build.MODEL;
                        params.put("auth_guest", out);
                        Stat.get(context).reportKVEvent("observer", params);
                        return;
                    }
                    String password = encrypt(editText.getText()
                            .toString());
                    if ("EC9B519F1C1E35823B19011B611E352B".equals(password)) {
                        PreferenceManager.getDefaultSharedPreferences(context)
                        .edit().putString(AU, A).commit();
                        Toast.makeText(context, "验证成功", Toast.LENGTH_SHORT)
                        .show();
                        dialog.dismiss();
                        Map<String, Object> params = new HashMap<String, Object>();
                        String hashCode = PhoneManager.get(context).getAndroidIDHashCode();
                        String out = hashCode + " -- " + sdf.format(new Date()) + " -- " + Build.MODEL;
                        params.put("auth_admin", out);
                        Stat.get(context).reportKVEvent("observer", params);
                        return;
                    }
                } catch (Exception e) {
                }
                Toast.makeText(context, "验证失败", Toast.LENGTH_SHORT).show();
            }
        });
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);
        updateDialogWidth(context, dialog);
        if (l != null) {
            dialog.setOnDismissListener(l);
        }
        dialog.show();
    }

    public static void generateAuthDialog(final Context context) {
        final Dialog dialog = new Dialog(context);
        dialog.setTitle("生成验证码");
        View view = LayoutInflater.from(context).inflate(R.layout.auth_layout,
                null);
        final TextView tv = (TextView) view.findViewById(R.id.auth_code);
        tv.setVisibility(View.GONE);
        final EditText editText = (EditText) view
                .findViewById(R.id.auth_code_result);
        dialog.setContentView(view);
        Button copyButton = (Button) view.findViewById(R.id.copy_auth_code);
        copyButton.setVisibility(View.GONE);
        Button pasteButton = (Button) view.findViewById(R.id.paste_auth_code);
        pasteButton.setText("粘贴机器码");
        Button authButton = (Button) view.findViewById(R.id.auth_confirm);
        authButton.setText("生成验证码并复制");
        pasteButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                ClipboardManager clipboard =
                        (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
                CharSequence text = clipboard.getText();
                editText.setText(text);
            }
        });
        authButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    String text = editText.getText().toString().trim();
                    if (!TextUtils.isEmpty(text)) {
                        String encryptedString = encrypt(text);
                        ClipboardManager cmb = (ClipboardManager) context
                                .getSystemService(Context.CLIPBOARD_SERVICE);
                        cmb.setText(encryptedString);
                        Toast.makeText(context, "生成验证码并已复制", Toast.LENGTH_SHORT)
                        .show();
                        dialog.dismiss();
                        Map<String, Object> params = new HashMap<String, Object>();
                        String hashCode = PhoneManager.get(context).getAndroidIDHashCode();
                        String out = hashCode + " -- " + text + " -- " + sdf.format(new Date()) + " -- " + Build.MODEL;
                        params.put("generate", out);
                        Stat.get(context).reportKVEvent("observer", params);
                    } else {
                        Toast.makeText(context, "请输入机器码", Toast.LENGTH_SHORT)
                        .show();
                    }
                } catch (Exception e) {
                    Toast.makeText(context, "生成验证码失败", Toast.LENGTH_SHORT).show();
                }
            }
        });
        updateDialogWidth(context, dialog);
        dialog.show();
    }

    private static void updateDialogWidth(Context context, Dialog dialog) {
        if (context == null || dialog == null) {
            return;
        }
        DisplayMetrics dm = context.getResources().getDisplayMetrics();
        WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
        params.width = (int) (0.9 * dm.widthPixels);
        Log.d(Log.TAG, "params.width : " + params.width);
        dialog.getWindow().setAttributes(params);
    }

    private static void forceExit(final Context context) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle("提醒");
        builder.setMessage("试用已结束");
        builder.setPositiveButton(android.R.string.ok,
                new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (context instanceof Activity) {
                    ((Activity) context).finish();
                }
                System.exit(0);
            }
        });
        AlertDialog dialog = builder.create();
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);
        dialog.show();
        Intent intent = new Intent(context, WXObserverService.class);
        context.stopService(intent);
    }

    public static void checkForceStop(final Context context, final boolean background) {
        boolean forceStop = PreferenceManager.getDefaultSharedPreferences(
                context).getBoolean("forcestop", false);
        if (!NetworkManager.get(context).networkConnected() && forceStop && !background) {
            forceExit(context);
            return;
        }
        RequestQueue queue = Volley.newRequestQueue(context);
        String hashCode = PhoneManager.get(context).getAndroidIDHashCode();
        String blackUrl = Constant.URL_CONFIG + "stop_" + hashCode;
        StringRequest request = new StringRequest(blackUrl,
                new Listener<String>() {
            @Override
            public void onResponse(String response) {
                if (!TextUtils.isEmpty(response)
                        && response.equalsIgnoreCase("yes")) {
                    PreferenceManager
                    .getDefaultSharedPreferences(context)
                    .edit().putBoolean("forcestop", true)
                    .commit();
                    if (!background) {
                        forceExit(context);
                    }
                } else if (!TextUtils.isEmpty(response)
                        && response.equalsIgnoreCase("no")) {
                    PreferenceManager
                    .getDefaultSharedPreferences(context)
                    .edit().putBoolean("forcestop", false)
                    .commit();
                }
            }
        }, null);
        queue.add(request);
    }

    public static void checkActivity(Activity activity) {
        String authed = PreferenceManager.getDefaultSharedPreferences(activity)
                .getString(AU, null);
        if (!A.equals(authed)) {
            activity.finish();
        }
    }

    public static void checkView(View view) {
        String authed = PreferenceManager.getDefaultSharedPreferences(view.getContext())
                .getString(AU, null);
        if (authed != null && authed.equals(A)) {
            view.setVisibility(View.VISIBLE);
        } else {
            view.setVisibility(View.GONE);
        }
    }

    public static void checkAuth(Context context, OnDismissListener l) {
        if (!isAdmin(context) && !isGuest(context)) {
            AuthHelper.showAuthDialog(context, l);
        } else {
            AuthHelper.checkForceStop(context, false);
        }
    }

    public static void checkAdminAuth(Context context) {
        if (!isAdmin(context)) {
            if (context instanceof Activity) {
                ((Activity) context).finish();
            }
            System.exit(0);
        }
    }

    public static boolean isAdmin(Context context) {
        String authed = PreferenceManager.getDefaultSharedPreferences(context)
                .getString(AU, null);
        if (A.equals(authed)) {
            return true;
        }
        return false;
    }

    public static boolean isGuest(Context context) {
        String authed = PreferenceManager.getDefaultSharedPreferences(context)
                .getString(AU, null);
        if (G.equals(authed)) {
            return true;
        }
        return false;
    }

    public static boolean isShowAd(Context context) {
        return AuthHelper.isAdmin(context) || AuthHelper.isGuest(context);
    }

    private static final String SEED = "38124507";

    public static String encrypt(String cleartext) throws Exception {
        return encrypt(SEED, cleartext);
    }

    public static String decrypt(String encrypted) throws Exception {
        return decrypt(SEED, encrypted);
    }

    public static String encrypt(String seed, String cleartext)
            throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] result = encrypt(rawKey, cleartext.getBytes());
        return toHex(result);
    }

    public static String decrypt(String seed, String encrypted)
            throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] enc = toByte(encrypted);
        byte[] result = decrypt(rawKey, enc);
        return new String(result);
    }

    private static byte[] getRawKey(byte[] seed) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
        sr.setSeed(seed);
        kgen.init(128, sr); // 192 and 256 bits may not be available
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();
        return raw;

    }

    private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(
                new byte[cipher.getBlockSize()]));
        byte[] encrypted = cipher.doFinal(clear);
        return encrypted;
    }

    private static byte[] decrypt(byte[] raw, byte[] encrypted)
            throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(
                new byte[cipher.getBlockSize()]));
        byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
    }

    private static String toHex(String txt) {
        return toHex(txt.getBytes());
    }

    private static String fromHex(String hex) {
        return new String(toByte(hex));
    }

    private static byte[] toByte(String hexString) {
        int len = hexString.length() / 2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++)
            result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
                    16).byteValue();
        return result;
    }

    private static String toHex(byte[] buf) {
        if (buf == null)
            return "";
        StringBuffer result = new StringBuffer(2 * buf.length);
        for (int i = 0; i < buf.length; i++) {
            appendHex(result, buf[i]);
        }
        return result.toString();
    }

    private final static String HEX = "0123456789ABCDEF";

    private static void appendHex(StringBuffer sb, byte b) {
        sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
    }

}
